package net.llz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.llz.config.RabbitMQConfig;
import net.llz.enums.*;
import net.llz.exception.BizException;
import net.llz.feign.ProduceOrderFeignService;
import net.llz.interceptor.LoginInterceptor;
import net.llz.mapper.CouponRecordMapper;
import net.llz.mapper.CouponTaskMapper;
import net.llz.model.CouponRecordDO;
import net.llz.model.CouponRecordMessage;
import net.llz.model.CouponTaskDO;
import net.llz.model.LoginUser;
import net.llz.request.LockCouponRecordRequest;
import net.llz.service.CouponRecordService;
import net.llz.util.JsonData;
import net.llz.vo.CouponRecordVO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CouponRecordServiceImpl implements CouponRecordService {

    @Autowired
    private CouponRecordMapper couponRecordMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;
    @Autowired
    private CouponTaskMapper couponTaskMapper;

    @Autowired
    private ProduceOrderFeignService orderFeignService;
    @Override
    public  Map<String, Object> page(int page, int size) {

        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        Page<CouponRecordDO> pageInfo = new Page<>(page,size);

        IPage<CouponRecordDO> recordDOIPage = couponRecordMapper.selectPage(pageInfo,new QueryWrapper<CouponRecordDO>()
                .eq("user_id",loginUser.getId()).orderByDesc("create_time"));

        Map<String,Object> pageMap = new HashMap<>(3);

        pageMap.put("total_record",recordDOIPage.getTotal());
        pageMap.put("total_page",recordDOIPage.getPages());
        pageMap.put("current_data",recordDOIPage.getRecords().stream().map(obj->beanProcess(obj)).collect(Collectors.toList()));

            return pageMap;

    }

    @Override
    public CouponRecordVO findById(long recordId) {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        CouponRecordDO couponRecordDO = couponRecordMapper.selectOne(new QueryWrapper<CouponRecordDO>().eq("user_id",loginUser.getId()));

        return beanProcess(couponRecordDO);
    }

    /**
     * 锁定优惠卷
     * 1)锁定优惠卷记录
     * 2)插入优惠卷记录
     * 3)发送延迟消息
     * @param recordRequest
     * @return
     */
    @Override
    public JsonData lockCouponRecords(LockCouponRecordRequest recordRequest) throws BizException {
        LoginUser loginUser =LoginInterceptor.threadLocal.get();

        //orderOutTradeNo 订单号
        String orderOutTradeNo = recordRequest.getOrderOutTrade();
        //lockCouponRecordIds 优惠卷id
        List<Long> lockCouponRecordIds = recordRequest.getLockCouponRecordIds();

        //lockUseStateBatch 锁定优惠卷
       int updateRows=  couponRecordMapper.lockUseStateBatch(loginUser.getId(), CouponStateEnum.USED.name(),lockCouponRecordIds);

            //couponTaskDOList 批量task订单号
            List<CouponTaskDO> couponTaskDOList = lockCouponRecordIds.stream().map(obj ->{
           CouponTaskDO couponTaskDO = new CouponTaskDO();
           couponTaskDO.setCreateTime(new Date());
           couponTaskDO.setOutTradeNo(orderOutTradeNo);
           couponTaskDO.setLockState(StockTaskStateEnum.LOCK.name());
           couponTaskDO.setCouponRecordId(obj);
           return couponTaskDO;
       }).collect(Collectors.toList());

            //insertRows 插入task行数
            int insertRows = couponTaskMapper.insertBatch(couponTaskDOList);
            log.info("优惠卷记录锁定updateRow{}",updateRows);
            log.info("新增卷记录taskRow{}",insertRows);

            if (lockCouponRecordIds.size() == insertRows && insertRows== updateRows){
                CouponRecordMessage couponRecordMessage = new CouponRecordMessage();
                couponRecordMessage.setOutTradeNo(orderOutTradeNo);
                couponRecordMessage.setTaskId(couponRecordMessage.getTaskId());
                rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(),rabbitMQConfig.getCouponReleaseRoutingKey(),couponRecordMessage);
                log.info("优惠券锁定消息发送成功:{}",couponRecordMessage.toString());

                return JsonData.buildSuccess();
            }else {
                throw  new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL);
            }

    }

    /**
     * 解锁优惠卷记录
     * 1）查询task是否存在
     * 2）查询订单状态
     * @param recordMessage
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean releaseCouponRecord(CouponRecordMessage recordMessage) {    //查询下task是否存
        CouponTaskDO taskDO = couponTaskMapper.selectOne(new QueryWrapper<CouponTaskDO>()
                .eq("id",recordMessage.getTaskId()));
        if(taskDO==null){
            log.warn("工作单不存，消息:{}",recordMessage);
            return true;
        }
        //lock状态才处理
        if(taskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){

            //查询订单状态
            JsonData jsonData = orderFeignService.queryProductOrderState(recordMessage.getOutTradeNo());
            if(jsonData.getCode()==0){
                //正常响应，判断订单状态
                String state = jsonData.getData().toString();
                if(ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){
                    //状态是NEW新建状态，则返回给消息队，列重新投递
                    log.warn("订单状态是NEW,返回给消息队列，重新投递:{}",recordMessage);
                    return false;
                }

                //如果是已经支付
                if(ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){
                    //如果已经支付，修改task状态为finish
                    taskDO.setLockState(StockTaskStateEnum.FINISH.name());
                    couponTaskMapper.update(taskDO,new QueryWrapper<CouponTaskDO>().eq("id",recordMessage.getTaskId()));
                    log.info("订单已经支付，修改库存锁定工作单FINISH状态:{}",recordMessage);
                    return true;
                }
            }

            //订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW
            log.warn("订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW,message:{}",recordMessage);
            taskDO.setLockState(StockTaskStateEnum.CANCEL.name());

            couponTaskMapper.update(taskDO,new QueryWrapper<CouponTaskDO>()
                    .eq("id",recordMessage.getTaskId()));
            //恢复优惠券记录是NEW状态
            couponRecordMapper.updateState(taskDO.getCouponRecordId(),CouponStateEnum.NEW.name());

            return true;
        }else {
            log.warn("工作单状态不是LOCK,state={},消息体={}",taskDO.getLockState(),recordMessage);
            return true;
        }

//        //查询task_id是否存在
//       CouponTaskDO taskDO= couponTaskMapper.selectOne(new QueryWrapper<CouponTaskDO>().eq("id",recordMessage.getTaskId()));
//
//       if (taskDO == null){
//           log.warn("工作不存在:{}",recordMessage);
//           return true;
//       }
//
//       //如果在锁定状态
//        if (taskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){
//            //查询订单的状态
//            JsonData jsonData = produceOrderFeignService.queryProductOrderState(recordMessage.getOutTradeNo());
//            if (jsonData.getCode() == 0){
//                //正常状态
//                String state = jsonData.getData().toString();
//                if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){
//                    //优惠卷状态为NEW，返回给消息队列，重新投递：{}
//                    log.warn("优惠卷状态为NEW，返回给消息队列，重新投递：{}",recordMessage);
//                    return false;
//                }
//                if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){
//                    //如果是支付状态就修改taskd的状态为finish
//                    taskDO.setLockState(StockTaskStateEnum.FINISH.name());
//                    couponTaskMapper.update(taskDO,new QueryWrapper<CouponTaskDO>().eq("id",recordMessage.getTaskId()));
//                    log.info("订单已经支付，修改库存锁定工作单FINISH状态:{}",recordMessage);
//
//                    return true;
//                }
//            }
//            //订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW
//            log.warn("订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW,message:{}",recordMessage);
//            taskDO.setLockState(StockTaskStateEnum.CANCEL.name());
//            couponTaskMapper.update(taskDO,new QueryWrapper<CouponTaskDO>().eq("id",recordMessage.getTaskId()));
//
//            //恢复优惠卷使用状态
//            couponRecordMapper.updateState(taskDO.getCouponRecordId(),CouponStateEnum.NEW.name());
//
//            return true;
//        }else {
//            log.warn("工作状态不是LOCK{},消息体{}",taskDO.getLockState(),recordMessage);
//            return true;
//        }

    }


    private CouponRecordVO beanProcess(CouponRecordDO couponRecordDO){
        CouponRecordVO recordVO = new CouponRecordVO();

        BeanUtils.copyProperties(couponRecordDO,recordVO);
        return  recordVO;
    }
}
